﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using VIX;

namespace SampleApplication
{
    public partial class frmMain : Form
    {
        Host host;

        public frmMain()
        {
            InitializeComponent();

            // preselect values
            cbActions.SelectedIndex = 0;
            cbHostType.SelectedIndex = 2;
        }

        private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            // disconnect the host when the form is closed, to ensure VIX can clean up stuff
            if (host != null)
                host.Disconnect();
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            VIX.Enums.VIX_SERVICEPROVIDER hostType = VIX.Enums.VIX_SERVICEPROVIDER.DEFAULT;

            switch (cbHostType.SelectedIndex)
            {
                case 0:
                    hostType = VIX.Enums.VIX_SERVICEPROVIDER.DEFAULT;
                    break;

                case 1:
                    hostType = VIX.Enums.VIX_SERVICEPROVIDER.VMWARE_SERVER;
                    break;

                case 2:
                    hostType = VIX.Enums.VIX_SERVICEPROVIDER.VMWARE_VI_SERVER;
                    break;

                case 3:
                    hostType = VIX.Enums.VIX_SERVICEPROVIDER.VMWARE_WORKSTATION;
                    break;

                case 4:
                    hostType = VIX.Enums.VIX_SERVICEPROVIDER.VMWARE_PLAYER;
                    break;

                default:
                    break;
            }

            string hostURL = "";

            // for VMware Workstation, VMware Player or Server 1.x we must use the hostname, for other hosts we use an URL
            if (hostType == VIX.Enums.VIX_SERVICEPROVIDER.VMWARE_WORKSTATION || hostType == VIX.Enums.VIX_SERVICEPROVIDER.VMWARE_PLAYER || hostType == VIX.Enums.VIX_SERVICEPROVIDER.VMWARE_SERVER)
                hostURL = txtServerHostname.Text;
            else
                hostURL = "https://" + txtServerHostname.Text + ":" + nudPort.Value + "/sdk";

            try
            {
                host = VixCOMWrapper.Instance.Connect(hostType, hostURL, 0, txtUsername.Text, txtPW.Text);

                grpActions.Enabled = true;
            }
            catch (VixException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnGetRegVMs_Click(object sender, EventArgs e)
        {
            try
            {
                List<string> vms = host.FindItems(VIX.Enums.VIX_FIND.REGISTERED_VMS);

                lstVMs.Items.Clear();
                lstVMs.Items.AddRange(vms.ToArray());
            }
            catch (VixException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnGetRunningVMs_Click(object sender, EventArgs e)
        {
            lstVMs.Items.Clear();

            List<string> vms;

            try
            {
                vms = host.FindItems(VIX.Enums.VIX_FIND.RUNNING_VMS);
            }
            // if no VMs are running, the RUNNING_VMS property is not available and FindItems() may throw an exception
            catch (VixException ex)
            {
                return;
            }

            lstVMs.Items.AddRange(vms.ToArray());
        }

        private void btnDo_Click(object sender, EventArgs e)
        {
            if (lstVMs.SelectedItems.Count == 0)
                return;

            string vm = lstVMs.SelectedItem.ToString();

            try
            {
                VM vmx = host.OpenVMEx(vm, null);

                /*   0 Power On
                 *   1 Power Off
                 *   2 Suspend
                 *   3 Resume
                 *   4 Take Snapshot
                 *   5 Revert to Snapshot
                 *   6 Run calc.exe in Guest
                 *   7 Query Information
                 *   8 List contents of C:\ directory
                 *   9 List processes in Guest
                 */

                switch (cbActions.SelectedIndex)
                {
                    case 0:
                        vmx.PowerOn(VIX.Enums.VIX_VMPOWEROP.NORMAL);
                        break;

                    case 1:
                        vmx.PowerOff(VIX.Enums.VIX_VMPOWEROP.NORMAL);
                        break;

                    case 2:
                        vmx.Suspend();
                        break;

                    case 3:
                        vmx.PowerOn(VIX.Enums.VIX_VMPOWEROP.NORMAL);
                        break;

                    case 4:
                        vmx.CreateSnapshot("Snapshot", "", false);
                        break;

                    case 5:
                        vmx.RevertToSnapshot(vmx.GetRootSnapshot(0), VIX.Enums.VIX_VMPOWEROP.NORMAL);
                        break;

                    case 6:
                        // we must establish an authentication context in the guest before we can run programs
                        vmx.LoginInGuest(txtUsername.Text, txtPW.Text, true);
                        vmx.RunProgramInGuest(@"C:\Windows\system32\calc.exe", "", true, false, false);
                        break;

                    case 7:
                        QueryInformation(vmx);
                        break;

                    case 8:
                        // we must establish an authentication context in the guest before we can list a directory
                        vmx.LoginInGuest(txtUsername.Text, txtPW.Text, true);
                        ListDirectory(vmx);
                        break;

                    case 9:
                        // we must establish an authentication context in the guest before we can list a directory
                        vmx.LoginInGuest(txtUsername.Text, txtPW.Text, true);
                        ListProcesses(vmx);
                        break;

                    default:
                        break;
                }
            }
            catch (VixException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void ListProcesses(VM vmx)
        {
            List<VIX.VM.GuestProcess> proc = vmx.ListProcessesInGuest();

            lstResults.Items.Clear();

            // loop through each result
            foreach (VIX.VM.GuestProcess res in proc)
            {
                lstResults.Items.Add("Process name: " + res.Name);
                lstResults.Items.Add("Process owner: " + res.Owner);
                lstResults.Items.Add("Process id: " + res.Id.ToString());
                lstResults.Items.Add("Command line: " + res.CommandLine ?? "N/A");
                lstResults.Items.Add("------------------------------------------");
            }
        }

        private void ListDirectory(VM vmx)
        {
            List<VIX.VM.GuestFileOrDirectory> dir = vmx.ListDirectoryInGuest(@"C:\");

            lstResults.Items.Clear();

            // loop through each result
            foreach (VIX.VM.GuestFileOrDirectory res in dir)
            {
                lstResults.Items.Add("File name: " + res.Name);
                lstResults.Items.Add("Directory: " + res.IsDirectory.ToString());
                lstResults.Items.Add("Modification time: " + res.ModificationDate.ToLocalTime().ToString());
                lstResults.Items.Add("------------------------------------------");
            }
        }

        private void QueryInformation(VM vmx)
        {
            try
            {
                // according to the documentation, the value of VM_TOOLS_STATE is only valid after calling WaitForToolsInGuest();
                vmx.WaitForToolsInGuest(10);
            }
            catch { }

            List<object> result = vmx.GetProperties(new VIX.Enums.VIX_PROPERTY[]
                                                        {
                                                            VIX.Enums.VIX_PROPERTY.VM_POWER_STATE,
                                                            VIX.Enums.VIX_PROPERTY.VM_TOOLS_STATE, 
                                                            VIX.Enums.VIX_PROPERTY.VM_VMX_PATHNAME, 
                                                            VIX.Enums.VIX_PROPERTY.VM_SUPPORTED_FEATURES, 
                                                            VIX.Enums.VIX_PROPERTY.VM_MEMORY_SIZE, 
                                                            VIX.Enums.VIX_PROPERTY.VM_NUM_VCPUS, 
                                                            VIX.Enums.VIX_PROPERTY.VM_READ_ONLY
                                                        });

            string ip = "N/A";

            try
            {
                ip = vmx.ReadVariable(VIX.Enums.VIX_VM.GUEST_VARIABLE, "ip");
            }
            catch { }

            lstResults.Items.Clear();

            lstResults.Items.Add("VM_POWER_STATE: " + ((VIX.Enums.VIX_POWERSTATE)result[0]).ToString());
            lstResults.Items.Add("VM_TOOLS_STATE: " + ((VIX.Enums.VIX_TOOLSSTATE)result[1]).ToString());
            lstResults.Items.Add("VM_VMX_PATHNAME: " + result[2].ToString());
            lstResults.Items.Add("VM_SUPPORTED_FEATURES: " + ((VIX.Enums.VIX_VM_SUPPORT)result[3]).ToString());
            lstResults.Items.Add("VM_MEMORY_SIZE: " + result[4].ToString());
            lstResults.Items.Add("VM_NUM_VCPUS: " + result[5].ToString());
            lstResults.Items.Add("VM_READ_ONLY: " + result[6].ToString());
            lstResults.Items.Add("IP: " + ip);
        }
    }
}
